﻿using System;
using System.Collections.Specialized;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.StsAdmin;
using Microsoft.SharePoint.Utilities;
using MSPE.Public.FOSS.AutoStatusPlus.Common;
using MSPE.Public.FOSS.AutoStatusPlus.StsAdm.OperationHelpers;
using MSPE.Public.FOSS.AutoStatusPlus.StsAdm.SPValidators;

namespace MSPE.Public.FOSS.AutoStatusPlus.StsAdm.Commands
{
    public class AspSetPwaSite : SPOperation
    {
        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="AspSetPwaSite"/> class.
        /// </summary>
        public AspSetPwaSite()
        {
            SPParamCollection _parameters = new SPParamCollection
                                               {
                                                   new SPParam(GlobalConstants.UrlParamName, GlobalConstants.UrlParamName, true, null,
                                                               new SPUrlValidator(),
                                                               "Please specify the PWA site URL."),
                                                   new SPParam(GlobalConstants.SspNameParamName, GlobalConstants.SspNameParamName, true,
                                                               null, new SPNonEmptyValidator(),
                                                               "Please specify the SSP Name."),
                                                   new SPParam(GlobalConstants.SspHostnameParamName, GlobalConstants.SspHostnameParamName, false,
                                                               null, new SPNullOrNonEmptyValidator(),
                                                               "Please specify the SSP Hostname."),
                                                   new SPParam(GlobalConstants.DbServerParamName, GlobalConstants.DbServerParamName, true,
                                                               null, new SPNonEmptyValidator(),
                                                               "Please specify the Database Server."),
                                                   new SPParam(GlobalConstants.DbNameParamName, GlobalConstants.DbNameParamName, true,
                                                               null, new SPNonEmptyValidator(),
                                                               "Please specify the name of the Reporting Database."),
                                                   new SPParam(GlobalConstants.DbUseIntegratedAuthParamName,
                                                               GlobalConstants.DbUseIntegratedAuthParamName, true, null,
                                                               new SPTrueFalseValidator(),
                                                               "Please specify whether to use Integrated Authentication."),
                                                   new SPParam(GlobalConstants.DbUserParamName, GlobalConstants.DbUserParamName, false,
                                                               null, new SPNullOrNonEmptyValidator(),
                                                               "Please specify the database user account (e.g. DOMAIN\\User)."),
                                                   new SPParam(GlobalConstants.DbPasswordParamName, GlobalConstants.DbPasswordParamName,
                                                               false, null, new SPNullOrNonEmptyValidator(),
                                                               "Please specify the database user account password.")
                                               };

            StringBuilder _sb = new StringBuilder();
            _sb.AppendLine("-url <URL of PWA Site>");
            _sb.AppendLine("\t-sspname <SSP Name>");
            _sb.AppendLine("\t-dbserver <Database Server Hostname>");
            _sb.AppendLine("\t-dbname <Reporting Database Name>");
            _sb.AppendLine("\t-useintegratedauth <true | false>");
            _sb.AppendLine("\t[-dbuser] <Database account name>");
            _sb.AppendLine("\t[-dbpass] <Database account password>");
            _sb.AppendLine("\t[-ssphostname] <Application Server Hostname>");
            _sb.AppendLine();
            _sb.AppendLine();
            _sb.AppendLine("\tThis command configures AutoStatusPlus for a particular");
            _sb.AppendLine("\tPWA site (i.e. Project Server 2007 instance).");
            _sb.AppendLine();
            _sb.AppendLine("\tThe ssphostname parameter is only relevant if your architecture");
            _sb.AppendLine("\tsegments the Application and Web tiers.");
            _sb.AppendLine();
            _sb.AppendLine("\tIf the useintegratedauth parameter is set to true, then");
            _sb.AppendLine("\tthe dbuser and dbpass parameters are ignored.");
            _sb.AppendLine("\tHowever, if the useintegratedauth parameter is set to false,");
            _sb.AppendLine("\tthen the dbuser and dbpass parameters are required.");

            Init(_parameters, _sb.ToString());
        }
        #endregion // Constructors

        #region Methods
        #region Overrides
        public override int Execute(string command, StringDictionary keyValues, out string output)
        {
            throw new NotImplementedException();
        } // Execute()

        /// <summary>
        /// Gets the help message.
        /// </summary>
        /// <param name="command">The command.</param>
        /// <returns></returns>
        public override string GetHelpMessage(string command)
        {
            return HelpMessage;
        } // GetHelpMessage()

        /// <summary>
        /// Runs the specified command.
        /// </summary>
        /// <param name="command">The command.</param>
        /// <param name="keyValues">The key values.</param>
        /// <param name="output">The output.</param>
        /// <returns></returns>
        public override int Run(string command, StringDictionary keyValues, out string output)
        {
            SPSite _site = null;
            SPWeb _pwaWeb = null;
            SqlConnection _sqlConn = null;
            SqlCommand _sqlCmd = null;

            try
            {
                #region Read configuration settings from command line
                output = string.Empty;

                InitParameters(keyValues);

                // Read params into local fields
                string _dbName = Params[GlobalConstants.DbNameParamName].Value;
                string _dbPassword = Params[GlobalConstants.DbPasswordParamName].Value;
                string _dbServer = Params[GlobalConstants.DbServerParamName].Value;
                string _dbUseIntegratedAuth = Params[GlobalConstants.DbUseIntegratedAuthParamName].Value;
                string _dbUser = Params[GlobalConstants.DbUserParamName].Value;
                string _sspHostname = Params[GlobalConstants.SspHostnameParamName].Value;
                string _sspName = Params[GlobalConstants.SspNameParamName].Value;
                string _url = Params[GlobalConstants.UrlParamName].Value.TrimEnd('/');
                #endregion // Read configuration settings from command line

                if (_dbUseIntegratedAuth == "false" && (_dbUser == null || _dbPassword == null))
                {
                    output = "You must specify a dbuser and dbpass if useintegratedauth is set to false.";
                    return (int) ErrorCodes.SyntaxError;
                }

                // Get the PWA site
                _site = new SPSite(_url);

                if (_site.Url != _url)
                    throw new Exception("You may only configure Project Web Access Sites.");

                _pwaWeb = _site.RootWeb;

                if (_pwaWeb == null)
                    throw new Exception("Could not load the Site at the specified URL.");

                if (_pwaWeb.WebTemplateId != GlobalConstants.PwaSiteTemplateId)
                    throw new Exception("You may only configure Project Web Access Sites.");

                #region Create DB Objects
                // Retrieve embedded script
                string _sqlScript = EmbeddedResource.GetString(GlobalConstants.SqlCreateScriptName);

                string _connString = Utility.BuildConnectionString(Convert.ToBoolean(_dbUseIntegratedAuth), _dbServer, _dbName, _dbUser, _dbPassword);
                
                // Create SQL Connection and Command Objects
                _sqlConn = new SqlConnection(_connString);
                _sqlConn.Open();

                if (_sqlConn.State == ConnectionState.Open)
                {
                    _sqlCmd = new SqlCommand(_sqlScript, _sqlConn);
                    _sqlCmd.CommandType = CommandType.Text;

                    _sqlCmd.ExecuteNonQuery();
                } // End if

                else
                    throw new Exception("Unable to establish a connection to SQL using the provided information.");
                #endregion // Create DB Objects
                
                #region Create and Set configuration settings
                // Create keys
                Utility.CreateConfigurationKeys(_pwaWeb);

                // Load web's property bag
                SPPropertyBag _pwaWebProperties = _pwaWeb.Properties;

                if (_pwaWebProperties == null)
                    throw new Exception("Unable to retrieve properties for Site.");

                if (!Utility.AllKeysExist(_pwaWeb))
                {
                    Utility.DeleteConfigurationKeys(_pwaWeb);
                    throw new ArgumentException("Creation of configuration keys failed.");
                } // End if

                // Create settings object
                Settings _inputSettings = Settings.LoadSettings(_pwaWeb);
                
                // Load configured settings
                _inputSettings.DbName = _dbName;
                _inputSettings.DbServer = _dbServer;
                _inputSettings.DbUseIntegratedAuth = Convert.ToBoolean(_dbUseIntegratedAuth);
                _inputSettings.SspName = _sspName;
                _inputSettings.SspHostname = _sspHostname;
                _inputSettings.WebIsConfigured = true;

                // Load default settings
                _inputSettings.Event = GlobalConstants.EventDefaultValue;
                _inputSettings.LogFilePath = GlobalConstants.LogFilePathDefaultValue;
                _inputSettings.LogFilePrefix = GlobalConstants.LogFilePrefixDefaultValue;
                _inputSettings.LogTimesheetEvents = GlobalConstants.LogTimesheetEventsDefaultValue;
                _inputSettings.LogUpdates = GlobalConstants.LogUpdatesDefaultValue;
                _inputSettings.NewLogFileEveryHour = GlobalConstants.NewLogFileEveryHourDefaultValue;
                _inputSettings.PollingInterval = GlobalConstants.PollingIntervalDefaultValue;
                _inputSettings.ProcessBlankLines = GlobalConstants.ProcessBlankLinesDefaultValue;
                _inputSettings.SubmitUpdates = GlobalConstants.SubmitUpdatesDefaultValue;

                if (!_inputSettings.DbUseIntegratedAuth)
                {
                    _inputSettings.DbUser = _dbUser;
                    _inputSettings.DbPassword = _dbPassword;
                } // End if

                else
                {
                    _inputSettings.DbUser = GlobalConstants.DbUserInitialValue;
                    _inputSettings.DbPassword = GlobalConstants.DbPasswordInitialValue;
                } // End else

                if (String.IsNullOrEmpty(_inputSettings.SspHostname))
                    _inputSettings.SspHostname = GlobalConstants.SspHostnameInitialValue;

                Settings.UpdateSettings(_pwaWeb, _inputSettings);
                #endregion //Set configuration settings

                // Use the ErrorCodes enum to return error codes: 
                // ErrorCodes.SyntaxError
                // ErrorCodes.GeneralError

                // Return 0 for success.
                return 0;
            } // End try

            catch (Exception ex)
            {
                throw new Exception("Error encountered while configuring site:\n\n" + ex.ToString());
            } // End catch

            finally
            {
                if (_pwaWeb != null) _pwaWeb.Dispose();
                if (_site != null) _site.Dispose();
                if (_sqlConn != null)
                {
                    if (_sqlConn.State != ConnectionState.Closed) _sqlConn.Close();
                    _sqlConn.Dispose();
                }
                if (_sqlCmd != null) _sqlCmd.Dispose();
            } // End finally
        } // Run()
        #endregion // Overrides
        #endregion // Methods
    }
}
